package hkr.vfu.bluecenter.backend;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import hkr.vfu.bluecenter.swipe_fragments.UpdateUIListener;

/**
 * Created by mattiasbowallius on 14/01/14.
 */
public class BluetoothManager {

    public static final int COMMAND_FINISHED = 1;
    private static BluetoothManager instance;
    private final ThreadPoolExecutor bluetoothThreadPoolExecutor;
    private final Queue<BluetoothTask> bluetoothWorkQueue;
    private final BlockingQueue<Runnable> blockingQueue;
    static {
        instance = new BluetoothManager();
    }

    public Handler handler;

    private BluetoothManager() {
        bluetoothWorkQueue = new LinkedBlockingQueue<BluetoothTask>();
        blockingQueue = new LinkedBlockingQueue<Runnable>();
        bluetoothThreadPoolExecutor = new ThreadPoolExecutor(1,1,1,TimeUnit.SECONDS, blockingQueue);

        handler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message message) {
                BluetoothTask bluetoothTask = (BluetoothTask) message.obj;
                UpdateUIListener updateUIListener = bluetoothTask.getUpdateUIListener();
                if (updateUIListener != null) {
                    switch (message.what) {
                        case COMMAND_FINISHED:
                            updateUIListener.updateUI();
                            recycleTask(bluetoothTask);
                            break;
                        default:
                            super.handleMessage(message);
                    }
                }
            }
        };
    }

    public static BluetoothManager getInstance() {
        return instance;
    }

    public static BluetoothTask runCommand(String macAddress, String command, UpdateUIListener updateUIListener) {
        BluetoothTask bluetoothTask = instance.bluetoothWorkQueue.poll();
        if (null == bluetoothTask) {
            bluetoothTask = new BluetoothTask();
        }
        bluetoothTask.setMacAddress(macAddress);
        bluetoothTask.setCommand(command);
        bluetoothTask.initializeBluetoothTask(BluetoothManager.instance, updateUIListener);
        instance.bluetoothThreadPoolExecutor.execute(bluetoothTask.getCommandRunnable());
        return bluetoothTask;
    }

    /**
     * Cancels all Threads in the ThreadPool
     */
    public static void cancelAll() {

        /*
         * Creates an array of tasks that's the same size as the task work queue
         */
        BluetoothTask[] taskArray = new BluetoothTask[instance.bluetoothWorkQueue.size()];

        // Populates the array with the task objects in the queue
        instance.bluetoothWorkQueue.toArray(taskArray);

        // Stores the array length in order to iterate over the array
        int taskArraylen = taskArray.length;

        /*
         * Locks on the singleton to ensure that other processes aren't mutating Threads, then
         * iterates over the array of tasks and interrupts the task's current Thread.
         */
        synchronized (instance) {

            // Iterates over the array of tasks
            for (int taskArrayIndex = 0; taskArrayIndex < taskArraylen; taskArrayIndex++) {

                // Gets the task's current thread
                Thread thread = taskArray[taskArrayIndex].getBluetoothThread();

                // if the Thread exists, post an interrupt to it
                if (null != thread) {
                    thread.interrupt();
                }
            }
        }
    }

    void recycleTask(BluetoothTask bluetoothTask) {

        // Frees up memory in the task
        bluetoothTask.recycle();

        // Puts the task object back into the queue for re-use.
        bluetoothWorkQueue.offer(bluetoothTask);
    }
}
